﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting;

namespace PloobsEngine.Factories
{
    /// <summary>
    /// Factory que cuida do gerenciamento de facrories
    /// funciona como um roteador, designando qual factory eh responsavel
    /// por cada request
    /// Factories podem ser adicionadas sem a necessidade de recompilar o projeto
    /// pode adicionar tambem factories em tempo real
    /// </summary>
    public class Manager : IFactory
    {
        private IDictionary<String, IFactory> _addressFactries;
        private EngineStuff engine;

        public Manager(EngineStuff engine)
        {
            this.engine = engine;            
            //_addressFactries.Add("TriggerFactory", new TriggerFactory());

            //_addressFactries = new Dictionary<String, IFactory>();
            //IDictionary<String, String> dic = BundleHandler.getBundle(filename);
            //foreach (string factoryname in dic.Keys)
            //{
            //    string[] names = dic[factoryname].Split('@');
            //    ObjectHandle oh =  Activator.CreateInstance(names[0],names[1]);
            //    object o = oh.Unwrap();
            //    IFactory fac = o as IFactory;
            //    fac.Init(engine);
            //    _addressFactries.Add(factoryname, (IFactory) o);
            //    System.Diagnostics.Debug.WriteLine("Factory adicionada ao manager " + factoryname);
            //}

        }

            
        
        #region IFactory Members

        public bool CanHandle(IRequest request)
        {
            return true;
        }

        /// <summary>
        /// Devolve o objeto pretendido pela request
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public object getObject(IRequest request)
        {
            IFactory factory = null;
            bool isCarregado = _addressFactries.TryGetValue(request.getAddress(), out factory);
            if ( isCarregado == false)
            {
                System.Diagnostics.Debug.WriteLine("Nao foi possivel encontrar factory responsavel por " + request.getAddress());
                throw new Exception("Nao foi possivel encontrar factory responsavel por " + request.getAddress());
                ///cuidar do erro
            }
            if(factory.CanHandle(request) != true)
                throw new Exception("Esta Factorie nao trata este tipo de request");

            return factory.getObject(request);
                       
        }

        #endregion

        /// <summary>
        /// Nao deve ser usado, esta aqui apenas caso aconteca algo imprevisto
        /// NAO DEVE SER USADO, pois pode dar pau quando usamos threads...
        /// </summary>
        /// <param name="factoryTypeName"></param>
        public void addFactory(String factoryAssemblyName , String factoryTypeName  )
        {
            System.Diagnostics.Debug.WriteLine("Nao deve ser usada esta maneira de adicionar factories");
            ObjectHandle oh = Activator.CreateInstance(factoryAssemblyName,factoryTypeName);
            object o = oh.Unwrap();
            IFactory fac = o as IFactory;
            fac.Init(engine);
            //Object o = objectDynamic.Unwrap();
            _addressFactries.Add(factoryTypeName, (IFactory)o);
        }


        #region IFactory Members


        public void Init(EngineStuff engine)
        {
            this.engine = engine;
        }

        #endregion
    }
}
